package com.eoner.baselibrary.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.util.Log;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.FutureTarget;
import com.eoner.baselib.application.BaseApplication;
import com.eoner.baselib.utils.sp.SPUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.math.BigDecimal;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.ResponseBody;


/**
 *
 */
public final class Utils {

    private static final String TAG = "Utils";

    @SuppressLint("StaticFieldLeak")
    private static Context context;

    private Utils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /**
     * 初始化工具类
     *
     * @param context 上下文
     */
    public static void init(@NonNull Context context) {
        Utils.context = context.getApplicationContext();
    }

    /**
     * 获取ApplicationContext
     *
     * @return ApplicationContext
     */
    public static Context getContext() {
        if (Utils.context == null) {
            context = BaseApplication.getInstance();
        }
        return context;
    }

    public static int getVersionCode(){
        PackageManager packageManager = context.getPackageManager();
        PackageInfo info = null;
        try {
            info = packageManager.getPackageInfo(context.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        int version = info.versionCode;
        return version;
    }

    public static String getVersionName(){
        PackageManager packageManager = context.getPackageManager();
        PackageInfo info = null;
        try {
            info = packageManager.getPackageInfo(context.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        String version = info.versionName;
        return version;
    }

    static String deviceId;
    public static String getDevicedId(){
        deviceId = getUniquePsuedoID();
        return deviceId;
    }

    public static long  getTimeStamp(){
        return System.currentTimeMillis()/1000;
    }

    //获得独一无二的Psuedo ID
    public static String getUniquePsuedoID() {
        String serial = null;
        String m_szDevIDShort = "35" +
                Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +
                Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +
                Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +
                Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +
                Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +
                Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +
                Build.USER.length() % 10; //13 位
        serial = Settings.Secure.getString(getContext().getContentResolver(), Settings.Secure.ANDROID_ID);
        if(TextUtils.isEmpty(serial)){
            serial = SPUtils.getInstance().getString("android_id_key");
        }
        if(TextUtils.isEmpty(serial)){
            serial = UUID.randomUUID().toString();
            SPUtils.getInstance().put("android_id_key",serial);
        }
        //使用硬件信息拼凑出来的15位号码
        String uuid = new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
        return uuid;
    }

    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager != null) {
            NetworkInfo[] allNetworkInfo = connectivityManager.getAllNetworkInfo();
            if (allNetworkInfo != null) {
                for (NetworkInfo networkInfo : allNetworkInfo) {
                    if (networkInfo.getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * @param textView
     * @param content
     * @param SizeSpan ¥的字体大小倍数
     */
    public static void set_price_style(TextView textView,String content,float SizeSpan){
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new RelativeSizeSpan(SizeSpan), 0, 2, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),2,content.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(spannableString);
    }

    public static void set_price_style(TextView textView,String content){
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new RelativeSizeSpan(0.75f), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0,content.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(spannableString);
    }

    public static void set_price_style2(TextView textView,String content){
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new RelativeSizeSpan(0.75f), 0, 2, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),2,content.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(spannableString);
    }

    public static void set_price_style1(TextView textView,String content){
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new RelativeSizeSpan(0.75f), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        String [] array = content.split("[.]");
        if(array.length == 2){
            spannableString.setSpan(new RelativeSizeSpan(0.75f), array [0].length() + 1, content.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        }
        spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0,content.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(spannableString);
    }

    public static void set_goodsdetail_price_style(TextView textView,String content){
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new RelativeSizeSpan(0.5f), 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0,content.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);;
        textView.setText(spannableString);
    }

    //加一个空格的样式
    public static void set_goodsdetail_price_style1(TextView textView,String content){
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new RelativeSizeSpan(0.5f), 0, 2, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0,content.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(spannableString);
    }

    public static void setFloatSize(TextView textView, String content, float textSize){
        if (!content.contains(".")) return;
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new RelativeSizeSpan(textSize), content.indexOf("."), content.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(spannableString);
    }

    public static void setDin(TextView textView,Context mContext){
        Typeface typeface = Typeface.createFromAsset(mContext.getAssets(), "fonts/din.ttf");
        textView.setTypeface(typeface);
    }

    public static void set_goodsdetail_goldprice_style(TextView textView,String integral_price){
        if (TextUtils.isEmpty(integral_price)) return;
        String content = integral_price + "金币";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new RelativeSizeSpan(0.5f), integral_price.length(), content.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        spannableString.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),0,integral_price.length(),Spannable.SPAN_INCLUSIVE_INCLUSIVE);;
        textView.setText(spannableString);
    }

    private static Pattern NUMBER_PATTERN = Pattern.compile("-?[0-9]+(\\.[0-9]+)?");

    public static Bitmap drawWXMiniBitmap(Bitmap bitmap, int width, int height) {
        Bitmap mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        // 用这个Bitmap生成一个Canvas,然后canvas就会把内容绘制到上面这个bitmap中
        Canvas mCanvas = new Canvas(mBitmap);
        // 绘制画笔
        Paint mPicturePaint = new Paint();
        // 绘制背景图片
        mCanvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPicturePaint);
        // 绘制图片的宽、高
        int width_head = bitmap.getWidth();
        int height_head = bitmap.getHeight();
        // 绘制图片－－保证其在水平方向居中
        mCanvas.drawBitmap(bitmap, (width - width_head) / 2, (height - height_head) / 2,
                mPicturePaint);
        // 保存绘图为本地图片
        mCanvas.save();
        mCanvas.restore();
        return mBitmap;
    }


//    public static byte[] getHtmlByteArray(final String url) {
//        URL htmlUrl = null;
//        InputStream inStream = null;
//        try {
//            htmlUrl = new URL(url);
//            URLConnection connection = htmlUrl.openConnection();
//            HttpURLConnection httpConnection = (HttpURLConnection)connection;
//            int responseCode = httpConnection.getResponseCode();
//            if(responseCode == HttpURLConnection.HTTP_OK){
//                inStream = httpConnection.getInputStream();
//            }
//        } catch (MalformedURLException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        byte[] data = inputStreamToByte(inStream);
//
//        return data;
//    }

    public static Bitmap getSharePic(String url) {
        //获取okHttp对象get请求
        try {
            OkHttpClient client = new OkHttpClient();
            //获取请求对象
            Request request = new Request.Builder().url(url).build();
            //获取响应体
            ResponseBody body = client.newCall(request).execute().body();
            //获取流
            InputStream in = body.byteStream();
            //转化为bitmap
            Bitmap bitmap = BitmapFactory.decodeStream(in);

            return bitmap;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Bitmap转换成byte[]并且进行压缩,压缩到不大于maxkb
     * @param bitmap
     * @param maxkb
     * @return
     */
    public static byte[] bmpToByteArray(Bitmap bitmap, int maxkb) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
        int options = 100;
        while (output.toByteArray().length/1024 > maxkb && options != 10) {
            output.reset(); //清空output
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, output);//这里压缩options%，把压缩后的数据存放到output中
            options -= 10;
            if (options == 0) {
                break;
            }
        }
        return output.toByteArray();
    }


    public static byte[] inputStreamToByte(InputStream is) {
        try{
            ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
            int ch;
            while ((ch = is.read()) != -1) {
                bytestream.write(ch);
            }
            byte imgdata[] = bytestream.toByteArray();
            bytestream.close();
            return imgdata;
        }catch(Exception e){
            e.printStackTrace();
        }

        return null;
    }

    public static byte[] readFromFile(String fileName, int offset, int len) {
        if (fileName == null) {
            return null;
        }

        File file = new File(fileName);
        if (!file.exists()) {
            Log.i(TAG, "readFromFile: file not found");
            return null;
        }

        if (len == -1) {
            len = (int) file.length();
        }

        Log.d(TAG, "readFromFile : offset = " + offset + " len = " + len + " offset + len = " + (offset + len));

        if(offset <0){
            Log.e(TAG, "readFromFile invalid offset:" + offset);
            return null;
        }
        if(len <=0 ){
            Log.e(TAG, "readFromFile invalid len:" + len);
            return null;
        }
        if(offset + len > (int) file.length()){
            Log.e(TAG, "readFromFile invalid file len:" + file.length());
            return null;
        }

        byte[] b = null;
        try {
            RandomAccessFile in = new RandomAccessFile(fileName, "r");
            b = new byte[len]; // ���������ļ���С������
            in.seek(offset);
            in.readFully(b);
            in.close();

        } catch (Exception e) {
            Log.e(TAG, "readFromFile : errMsg = " + e.getMessage());
            e.printStackTrace();
        }
        return b;
    }

    private static final int MAX_DECODE_PICTURE_SIZE = 1920 * 1440;
    public static Bitmap extractThumbNail(final String path, final int height, final int width, final boolean crop) {
//		Assert.assertTrue(path != null && !path.equals("") && height > 0 && width > 0);

        BitmapFactory.Options options = new BitmapFactory.Options();

        try {
            options.inJustDecodeBounds = true;
            Bitmap tmp = BitmapFactory.decodeFile(path, options);
            if (tmp != null) {
                tmp.recycle();
                tmp = null;
            }

            Log.d(TAG, "extractThumbNail: round=" + width + "x" + height + ", crop=" + crop);
            final double beY = options.outHeight * 1.0 / height;
            final double beX = options.outWidth * 1.0 / width;
            Log.d(TAG, "extractThumbNail: extract beX = " + beX + ", beY = " + beY);
            options.inSampleSize = (int) (crop ? (beY > beX ? beX : beY) : (beY < beX ? beX : beY));
            if (options.inSampleSize <= 1) {
                options.inSampleSize = 1;
            }

            // NOTE: out of memory error
            while (options.outHeight * options.outWidth / options.inSampleSize > MAX_DECODE_PICTURE_SIZE) {
                options.inSampleSize++;
            }

            int newHeight = height;
            int newWidth = width;
            if (crop) {
                if (beY > beX) {
                    newHeight = (int) (newWidth * 1.0 * options.outHeight / options.outWidth);
                } else {
                    newWidth = (int) (newHeight * 1.0 * options.outWidth / options.outHeight);
                }
            } else {
                if (beY < beX) {
                    newHeight = (int) (newWidth * 1.0 * options.outHeight / options.outWidth);
                } else {
                    newWidth = (int) (newHeight * 1.0 * options.outWidth / options.outHeight);
                }
            }

            options.inJustDecodeBounds = false;

            Log.i(TAG, "bitmap required size=" + newWidth + "x" + newHeight + ", orig=" + options.outWidth + "x" + options.outHeight + ", sample=" + options.inSampleSize);
            Bitmap bm = BitmapFactory.decodeFile(path, options);
            if (bm == null) {
                Log.e(TAG, "bitmap decode failed");
                return null;
            }

            Log.i(TAG, "bitmap decoded size=" + bm.getWidth() + "x" + bm.getHeight());
            final Bitmap scale = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true);
            if (scale != null) {
                bm.recycle();
                bm = scale;
            }

            if (crop) {
                final Bitmap cropped = Bitmap.createBitmap(bm, (bm.getWidth() - width) >> 1, (bm.getHeight() - height) >> 1, width, height);
                if (cropped == null) {
                    return bm;
                }

                bm.recycle();
                bm = cropped;
                Log.i(TAG, "bitmap croped size=" + bm.getWidth() + "x" + bm.getHeight());
            }
            return bm;

        } catch (final OutOfMemoryError e) {
            Log.e(TAG, "decode bitmap failed: " + e.getMessage());
            options = null;
        }

        return null;
    }

    public static void getBitmapResources(Context context, String
            url, LoadCallBack<Bitmap> callBack) {
        Observable.just(url).flatMap((Function<String, Observable<FutureTarget<Bitmap>>>) s -> Observable.just(Glide.with(context).asBitmap().load(s).submit())).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).subscribe(new Observer<FutureTarget<Bitmap>>() {
            private Disposable mDisposable;

            @Override
            public void onSubscribe(Disposable d) {
                mDisposable = d;
            }

            @Override
            public void onNext(FutureTarget<Bitmap> bitmapFutureTarget) {
                try {
                    callBack.loadSuccess(bitmapFutureTarget.get());
                } catch (Exception e) {
                    e.printStackTrace();
                    callBack.loadFail();
                }
            }

            @Override
            public void onError(Throwable e) {
                callBack.loadFail();
                if (mDisposable != null && !mDisposable.isDisposed()) {
                    mDisposable.dispose();
                }
            }

            @Override
            public void onComplete() {
                if (mDisposable != null && !mDisposable.isDisposed()) {
                    mDisposable.dispose();
                }
            }
        });
    }

    public static byte[] bmpToByteArray(final Bitmap bitmap, final boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        //100不压缩，将压缩数据放入baos

        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
        int options = 100;
        //循环判断压缩后的图像是否大于128kb，大于继续压缩
        Log.e("----1>", "byteCount" + output.toByteArray().length);
        while (output.toByteArray().length / 1024 > 127 && options > 2) {
            output.reset();
            options -= 2;
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, output);
            Log.e("----2>", "byteCount" + output.toByteArray().length);
        }
        if (needRecycle && !bitmap.isRecycled()) {
            bitmap.recycle();
        }
        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static Bitmap compressBmp(final Bitmap bitmap, final boolean needRecycle) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        //100不压缩，将压缩数据放入baos

        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
        int options = 100;
        //循环判断压缩后的图像是否大于128kb，大于继续压缩
        Log.e("----1>", "byteCount" + output.toByteArray().length);
        while (output.toByteArray().length / 1024 > 127 && options > 2) {
            output.reset();
            options -= 2;
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, output);
            Log.e("----2>", "byteCount" + output.toByteArray().length);
        }
        if (needRecycle && !bitmap.isRecycled()) {
            bitmap.recycle();
        }
        byte[] result = output.toByteArray();
        try {
            output.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (result.length != 0) {
            return BitmapFactory.decodeByteArray(result, 0, result.length);
        } else {
            return null;
        }
    }

    /**
     * 昵称脱敏
     * */
    public static String transformNickName(String nickName) {
        //判断是否都是数字
        if (checkStrIsNum(nickName)) {
            //判断是否是11位
            if (nickName.length() == 11) {
                //判断第一位是否为1
                if (nickName.startsWith("1")) {
                    String[]chars = nickName.split("");
                    String first = chars[1];
                    String end = chars[chars.length-1];
                    nickName = first+"****"+end;
                    return nickName;
                }
            }
        }
        return nickName;
    }


    /**
     * 利用正则表达式来判断字符串是否为数字
     */
    private static boolean checkStrIsNum(String str) {
        String bigStr;
        try {
            /** 先将str转成BigDecimal，然后在转成String */
            bigStr = new BigDecimal(str).toString();
        } catch (Exception e) {
            /** 如果转换数字失败，说明该str并非全部为数字 */
            return false;
        }
        Matcher isNum = NUMBER_PATTERN.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }

    public static String decimalFormat(BigDecimal amount) {
        if(amount == null) {
            return "";
        }
        amount = amount.divide(BigDecimal.ONE,2, BigDecimal.ROUND_HALF_UP);
        String[] s = amount.toString().split("\\.");
        StringBuffer buffer = new StringBuffer();
        char[] cs = s[0].toCharArray();
        for(int i = cs.length - 1;i >= 0;i --) {
            buffer.append(cs[cs.length-i-1]);
            if((i)%3==0 && cs.length > 3 && i != 0) {
                buffer.append(",");
            }
        }
        buffer.append(".").append(s[1]);
        return buffer.toString();
    }

}
